#include "qrsagsmapflashtool.h"
#include "qgsmapmouseevent.h"
#include "qgslayertreenode.h"
#include "qgslayertreemodel.h"

QRSAGSMapFlashTool::QRSAGSMapFlashTool(QgsMapCanvas *mapCanvas, QgsLayerTreeView *layerTreeVeiw)
    : QgsMapTool(mapCanvas)
{
    this->mMapCanvas = mapCanvas;
    this->mLayerTreeView = layerTreeVeiw;
    this->mMapFlash = new QRSAGSMapFlash(this->mMapCanvas);
    this->mMapFlash->setOpacity(1.0);
    this->mTimer = new QTimer(this);
}

QRSAGSMapFlashTool::~QRSAGSMapFlashTool()
{
    delete this->mMapFlash;
    delete this->mMapCanvas;
    delete this->mLayerTreeView;
}

void QRSAGSMapFlashTool::activateConnect()
{
    connect(this->mMapCanvas, &QgsMapCanvas::mapCanvasRefreshed, this, &QRSAGSMapFlashTool::setMap);
    connect(this->mLayerTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QRSAGSMapFlashTool::setLayerFlash);
    connect(QgsProject::instance(), &QgsProject::removeAll, this, &QRSAGSMapFlashTool::disable);
    connect(this->mTimer, &QTimer::timeout, this, &QRSAGSMapFlashTool::setMapFlashOpacity);
    this->mTimer->start(500);
}

void QRSAGSMapFlashTool::deactivateConnect()
{
    disconnect(this->mMapCanvas, &QgsMapCanvas::mapCanvasRefreshed, this, &QRSAGSMapFlashTool::setMap);
    disconnect(this->mLayerTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QRSAGSMapFlashTool::setLayerFlash);
    disconnect(QgsProject::instance(), &QgsProject::removeAll, this, &QRSAGSMapFlashTool::disable);
    disconnect(this->mTimer, &QTimer::timeout, this, &QRSAGSMapFlashTool::setMapFlashOpacity);
    this->mTimer->stop();
}

void QRSAGSMapFlashTool::activate()
{
    this->mMapCanvas->setCursor(QCursor(Qt::PointingHandCursor));
    //建立信号与槽的连接
    this->activateConnect();
    this->disableFlash = false;
    this->setLayerFlash();
}

void QRSAGSMapFlashTool::deactivate()
{
    emit(this->deactivated());
    this->mMapFlash->clear();
    this->deactivateConnect();
}

void QRSAGSMapFlashTool::setLayerFlash()
{
    if(this->disableFlash){
        return;
    }

    //如果选中的第一个图层没有勾选显示的话，需要提醒勾选显示
    QModelIndex currentIndex = this->mLayerTreeView->currentIndex();
    QgsLayerTreeNode *layerTreeNode = this->mLayerTreeView->layerTreeModel()->index2node(currentIndex);
    if(!layerTreeNode->itemVisibilityChecked()){
        QMessageBox::information(new QWidget(), tr("Warm Tips"), tr("If you want to swipe with this maplayer, please to check it..."));
        return;
    }

    QList<QgsMapLayer*> mapLayers;
    if(layerTreeNode->inherits("QgsLayerTreeLayer")){
        QgsLayerTreeLayer *layerTreeLayer = (QgsLayerTreeLayer*)layerTreeNode;
        QgsMapLayer *layer = layerTreeLayer->layer();

        if(!layer->isSpatial()){
            return;
        }

        mapLayers.append(layer);
    }else {
        QgsLayerTreeGroup *layerTreeGroup = this->mLayerTreeView->currentGroupNode();
        if(layerTreeGroup->parent() == nullptr){
            return;
        }
        QList<QgsLayerTreeLayer *> layerTreeLayers = layerTreeGroup->findLayers();
        QList<QgsLayerTreeLayer *> layerTreeLayersTemp;
        for(QgsLayerTreeLayer *layerTreeLayer: layerTreeLayers){
            if(layerTreeLayer->itemVisibilityChecked()){
                layerTreeLayersTemp.append(layerTreeLayer);
                mapLayers.append(layerTreeLayer->layer());
            }
        }
        if(layerTreeLayersTemp.size() == 0){
            return;
        }
    }

    this->mMapFlash->clear();
    this->mMapFlash->setLayers(mapLayers);
    this->setMap();
}

void QRSAGSMapFlashTool::setMapFlashOpacity()
{
    qreal opa = this->mMapFlash->opacity();
    this->mMapFlash->setOpacity(1.0-opa);
}

void QRSAGSMapFlashTool::disable()
{
    this->mMapFlash->clear();
    this->disableFlash = true;
}

void QRSAGSMapFlashTool::setMap()
{
    if(this->mMapFlash->getMapLayers().size() == 0){
        return;
    }

    QgsMapSettings settings = this->mMapCanvas->mapSettings();
    settings.setLayers(this->mMapFlash->getMapLayers());
    settings.setBackgroundColor(QColor(Qt::transparent));

    this->mMapFlash->setRect(this->mMapCanvas->extent());

    QgsMapRendererParallelJob *job = new QgsMapRendererParallelJob(settings);
    job->start();
    connect(job, &QgsMapRendererParallelJob::finished, this, [=](){
        QImage image = job->renderedImage();
        if(this->mMapCanvas->property("retro").toBool()){
            image = image.scaled(image.width()/3, image.height()/3);
            image = image.convertToFormat(QImage::Format_Indexed8, Qt::OrderedDither | Qt::OrderedAlphaDither);
        }
        this->mMapFlash->setImage(image);
    });
    job->waitForFinished();
}
